package com.qijian.common.utils.poi;

import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.IOUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author gw
 */
public abstract class ExcelCustomizationTemplateAdapter {

    protected String fileName;
    protected Workbook wb;
    protected Sheet sheet;

    @SneakyThrows
    public void createWorkbook(String template) {
        ClassPathResource classPathResource = new ClassPathResource(template);
        this.fileName = template;
        this.wb = WorkbookFactory.create(classPathResource.getStream());
        ;
        this.sheet = wb.getSheetAt(0);
    }

    public ExcelCustomizationTemplateAdapter(String template) {
        createWorkbook(template);
    }

    /**
     * 新增一行数据并拷贝上一行的样式
     *
     * @param startRow 开始新增行数
     * @param cellNum  增加的列数
     */
    protected void insertRow(int startRow, int rowNum, int cellNum) {
        List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
        sheet.shiftRows(startRow, sheet.getLastRowNum(), rowNum, true, false);
//        for (CellRangeAddress cellRangeAddress : originMerged) {
//            //这里的8是插入行的index，表示这行之后才重新合并
//            if (cellRangeAddress.getFirstRow() > startRow) {
//                //你插入了几行就加几，我这里插入了一行，加1
//                int firstRow = cellRangeAddress.getFirstRow() + rowNum;
//                CellRangeAddress newCellRangeAddress = new CellRangeAddress(firstRow, (firstRow + (cellRangeAddress
//                        .getLastRow() - cellRangeAddress.getFirstRow())), cellRangeAddress.getFirstColumn(),
//                        cellRangeAddress.getLastColumn());
//                sheet.addMergedRegion(newCellRangeAddress);
//            }
//        }
//
//        //获取当前行
        Row rowSource = sheet.getRow(startRow + rowNum);
//        //获取当前行样式
        CellStyle rowStyle = rowSource.getRowStyle();
        for (int i = 0; i < rowNum; i++) {
            // 新增行
            Row rowInsert = sheet.createRow(startRow + i);
            if (rowStyle != null) {
                rowInsert.setRowStyle(rowStyle);
                rowInsert.setHeight(rowSource.getHeight());
            }
            for (int col = 0; col < cellNum; col++) {
                Cell cellSource = rowSource.getCell(col);
                Cell cellInsert = rowInsert.createCell(col);
                CellStyle cellStyle = cellSource.getCellStyle();
                //设置单元格样式　　　　
                if (cellStyle != null) {
                    cellInsert.setCellStyle(cellStyle);
                }
            }
        }
        for (CellRangeAddress cellRangeAddress : mergedRegions) {
            //表示这行之后才重新合并
            if (cellRangeAddress.getFirstRow() == startRow + rowNum) {
                for (int i = 0; i < rowNum; i++) {
                    CellRangeAddress newCellRangeAddress = new CellRangeAddress(startRow + i, startRow + i, cellRangeAddress.getFirstColumn(),
                            cellRangeAddress.getLastColumn());
                    sheet.addMergedRegion(newCellRangeAddress);
                }

            }
        }


    }

    /**
     * 对list数据源将其里面的数据导入到excel表单
     *
     * @param response 返回数据
     * @param data     导出数据集合
     */
    public void exportExcel(HttpServletResponse response, Object data) {
        try {
            String fileNamePre = writeSheet(data);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncodeUtil.encode((StrUtil.isNotBlank(fileNamePre) ? fileNamePre + "_" : "") + fileName, StandardCharsets.UTF_8));
            response.setCharacterEncoding("utf-8");
            disposeData(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void disposeData(OutputStream out) {
        try {
            wb.write(out);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            IOUtils.closeQuietly(wb);
            IOUtils.closeQuietly(out);
        }
    }

    protected Row getRow(int index) {
        Row row = sheet.getRow(index);
        if (row == null) {
            row = sheet.createRow(index);
        }
        return row;
    }

    protected Cell getCell(Row row, int index) {
        Cell cell = row.getCell(index);
        if (cell == null) {
            cell = row.createCell(index);
        }
        return cell;
    }

    protected String findItemAttr(String itemAttr, String prop) {
        if (StrUtil.isEmpty(prop)) {
            return null;
        }
        if (JSONUtil.isJsonArray(itemAttr)) {
            JSONArray attr = JSONUtil.parseArray(itemAttr);
            for (Object obj : attr) {
                JSONObject o = JSONUtil.parseObj(obj);
                if (prop.equals(o.getStr("name"))) {
                    Object value = o.get("value");
                    if (value == null) {
                        return null;
                    }
                    if (value.equals("")){
                        continue;
                    }
                    if (value instanceof Number) {
                        BigDecimal number = new BigDecimal(String.valueOf(value));
                        if (BigDecimal.ZERO.compareTo(number) == 0) {
                            continue;
                        }
                    }
                    return String.valueOf(value);
                }
            }
        } else if (JSONUtil.isJsonObj(itemAttr)) {
            JSONObject o = JSONUtil.parseObj(itemAttr);
            Object value = o.get(prop);
            if (value == null) {
                return null;
            }
            if (value instanceof Number) {
                BigDecimal number = new BigDecimal(String.valueOf(value));
                if (BigDecimal.ZERO.compareTo(number) == 0) {
                    return null;
                }
            }
            return String.valueOf(value);
        }
        return null;
    }

    /**
     * 根据具体的数据，重写sheet写入方法
     *
     * @param data 具体的数据
     * @return 文件名前缀
     */
    public abstract String writeSheet(Object data);
}
